from autobahn.asyncio.websocket import WebSocketClientProtocol, \
    WebSocketClientFactory
from autobahn.websocket.util import parse_url
import os
import json
from sys import stdin
try:
    import asyncio
except ImportError:
    # Trollius >= 0.3 was renamed
    import trollius as asyncio
    
from play import repeatPlayMp3, playOpen, playClose
from espeak import repeatPlayEspeak
from interval import setInterval

class MyClientProtocol(WebSocketClientProtocol):

    def onConnect(self, response):
        print("Server connected: {0}".format(response.peer))

    def onOpen(self):
        print("WebSocket connection open.")
        playOpen()
        self.is_closed = False
        self.heartBeat = 0

        def hello():
            self.heartBeat = self.heartBeat + 1
            if self.is_closed:
                return
            if self.heartBeat > 2:
                self._closeConnection()
                return
            print('send hello----')
            self.sendMessage(u'{"type": "heartBeat"}'.encode('utf8'))
            # self.sendMessage(b"\x00\x01\x03\x04", isBinary=True)
            self.factory.loop.call_later(10, hello)

        # start sending messages every second ..
        hello()

    def onMessage(self, payload, isBinary):
        # if isBinary:
        #     print("Binary message received: {0} bytes".format(len(payload)))
        # else:
        #     print("Text message received: {0}".format(payload.decode('utf8')))
        # stopPlay = repeatPlayMp3(payload.decode('utf8'))
        if not isBinary:
            try:
                msg = payload.decode('utf8')
                msgJson = json.loads(msg)
                if msgJson['type'] == 'heartBeat':
                    self.heartBeat = 0
                    return
                if self.cb is not None:
                    self.cb(msgJson)
            except Exception as e:
                print(e)

    def onClose(self, wasClean, code, reason):
        print("WebSocket connection closed: {0}".format(reason))
        self.is_closed = True

    def connection_lost(self, exc):
        print('The server closed the connection')
        print('Stop the event loop')
        playClose()
        self.factory.loop.stop()

    def setMessageCallback(self, cb):
        self.cb = cb

def getHostPort(url):
    (_, host, port, _, _, _) = parse_url(url)
    return (host, port)

repeatCount = 0
def startWebSocket(url, cb):
    '''
      :param url: websocket endpoint
      :type url: str

      :param cb: websocket receive message call back
      :type cb: function(message)

      :returns: fn -- stop event loop
    '''

    factory = WebSocketClientFactory(url)
    factory.protocol = MyClientProtocol

    host, port = getHostPort(url)
    loop = asyncio.get_event_loop()
    @setInterval(5)
    def repeat():
        global repeatCount
        coro = loop.create_connection(factory, host, port)
        try:
          (transport, protocol) = loop.run_until_complete(coro)
          protocol.setMessageCallback(cb)
          repeatCount = 0
          loop.run_forever()
        except Exception as ex:
          print('error--')
          print(ex)
          repeatCount = repeatCount + 1
          if repeatCount % 6 == 0:
            print('play close')
            playClose()
    
    stopped = repeat()

    def stop():
        stopped.set()
        loop.stop()
    return stop

def main():
  from dotenv import load_dotenv
  load_dotenv()
  url = os.getenv('wsUrl') + '/' + os.getenv('id')
  # url = 'ws://echo.websocket.org/'
  host, port= getHostPort(url)
  print('host: {0}, port: {1}'.format(host, port))
  def cb(msg):
    print(msg)
  stop = startWebSocket(url, cb)
  stdin.read(1)
  stop()

if __name__ == '__main__':
  main()
